﻿namespace UnityEditor.Controls.HierarchyControl.ViewModel
{
    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq.Expressions;
    using UnityEngine.Components;
    using UnityEngine.Core;
    using System.Windows.Controls;
    using System.Windows;

    /// <summary>
    /// One item in the treeview of of items
    /// </summary>
    public class HierarchyItem : INotifyPropertyChanged
    {
        private ObservableCollection<HierarchyItem> children;

        private bool isExpanded;

        private bool isSelected;

        private HierarchyItem parent;

        /// <summary>
        /// Standard constructor from itemName and link to parent
        /// </summary>
        /// <param name="itemName"></param>
        /// <param name="parent"></param>
        public HierarchyItem(HierarchyItem parent, GameObject gameObject)
        {
            this.GameObject = gameObject;
            this.Parent = parent;

            this.children = new ObservableCollection<HierarchyItem>();
            foreach (Transform transform in this.GameObject.Transform.Children)
            {
                children.Add(new HierarchyItem(this, transform.GameObject));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public ObservableCollection<HierarchyItem> Children
        {
            get
            {
                return this.children;
            }
            set
            {
                this.children = value;
                this.NotifyPropertyChanged(() => this.Children);
            }
        }

        public GameObject GameObject
        {
            set;
            get;
        }

        public bool IsExpanded
        {
            get
            {
                return isExpanded;
            }
            set
            {
                isExpanded = value;
                this.NotifyPropertyChanged(() => this.IsExpanded);
            }
        }

        public bool IsSelected
        {
            get
            {
                return isSelected;
            }
            set
            {
                isSelected = value;
                if (isSelected == false)
                {
                    IsEditing = false;
                }
                this.NotifyPropertyChanged(() => this.IsSelected);
            }
        }

        public string Name
        {
            get
            {
                return this.GameObject.Name;
            }

            set
            {
                this.GameObject.Name = value;
                this.NotifyPropertyChanged(() => this.Name);
            }
        }

        //public static readonly DependencyProperty IsEditingProperty = DependencyProperty.Register("IsEditing", typeof(bool), typeof(HierarchyItem), new UIPropertyMetadata(false));
        //public bool IsEditing
        //{
        //    get { return (bool)GetValue(IsEditingProperty); }
        //    set { SetValue(IsEditingProperty, value); }
        //}

        private bool isEditing = false;
        public bool IsEditing
        {
            get
            {
                return isEditing;
            }
            set
            {
                isEditing = value;
                this.NotifyPropertyChanged(() => this.IsEditing);
            }
        }

        public HierarchyItem Parent
        {
            get
            {
                return this.parent;
            }

            set
            {
                this.parent = value;
                this.NotifyPropertyChanged(() => this.Parent);
            }
        }

        public void AddChild(HierarchyItem child)
        {
            this.Children.Add(child);
            child.Parent = this;

            if (this.GameObject.Transform.Children.Contains(child.GameObject.Transform) == false)
                this.GameObject.AddChild(child.GameObject);
        }

        public void RemoveChild(HierarchyItem child)
        {
            this.Children.Remove(child);

            if (this.GameObject.Transform.Children.Contains(child.GameObject.Transform) == true)
                this.GameObject.Transform.Children.Remove(child.GameObject.Transform);
        }

        public bool IsAncestorOf(HierarchyItem child)
        {
            foreach (HierarchyItem c in this.Children)
                if (c == child || c.IsAncestorOf(child))
                    return true;
            return false;
        }

        public void NotifyPropertyChanged<TProperty>(Expression<Func<TProperty>> property)
        {
            var lambda = (LambdaExpression)property;
            MemberExpression memberExpression;
            if (lambda.Body is UnaryExpression)
            {
                var unaryExpression = (UnaryExpression)lambda.Body;
                memberExpression = (MemberExpression)unaryExpression.Operand;
            }
            else
                memberExpression = (MemberExpression)lambda.Body;
            this.OnPropertyChanged(memberExpression.Member.Name);
        }

        public void TryLoadChildren(uint tryLoadDepth = 1)
        {
            // if (tryLoadDepth == 0)
            //    return;

            // uint nextLoadDepth = (uint)tryLoadDepth - 1 >= 0 ? tryLoadDepth - 1 : 0;
            //if (this.IsFullyLoaded == false && tryLoadDepth >= 1)
            //    if (this.IsFolder)
            // {
            //        this.Children.Clear();

            // string path = this.FullPath;
            //        string[] directoryNames = Directory.GetDirectories(path);
            // foreach (var directoryName in directoryNames)
            //        {
            // var item = new HierarchyItem(directoryName, this, nextLoadDepth);
            //            this.Children.Add(item);
            // }
            //        string[] filePaths = Directory.GetFiles(path);
            // foreach (var fileName in filePaths)
            //        {
            // var item = new HierarchyItem(fileName, this, nextLoadDepth);
            //            this.Children.Add(item);
            // }
            //    }

            // this.IsFullyLoaded = true;
            //}

            // foreach (HierarchyItem child in this.Children)
            //    child.TryLoadChildren(nextLoadDepth);
        }

        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}
